package com.ddd.mill.infrastructure.utils;


import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * Created by zhouxj6112 on 2019/12/17.
 */
public class ImageUtil {
    // Endpoint以杭州为例，其它Region请按实际情况填写。
    private static final String endpoint = "http://oss-cn-shenzhen.aliyuncs.com";
    // 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
    private static final String accessKeyId = "LTAINmC91NqIGN38";
    private static final String accessKeySecret = "Hh10dQPjq1jMLLSpbDAR05ZzR3nXsU";
    private static final Map<String, String> type_contentType = new HashMap<String, String>(){
        {
            put("gif", "image/gif");
            put("bmp", "image/bmp");
            put("webp", "image/webp");
            put("jpg", "image/jpg");
            put("png", "multipart/form-data");
            put("txt", "text/plain");
            put("mp4", "video/mpeg4");
            put("html", "text/html");
            put("pdf", "application/pdf");
        }
    };

    /***
     * 上传图片到OSS服务
     * @param multipartFile
     * @param folderName: 上传文件存放的文件夹名称,可选
     * @return 图片存储返回的url
     */
    public static String uploadImage(MultipartFile multipartFile, String folderName){
        return uploadImage(multipartFile, folderName, "qncloudprintfile");
    }

    /***
     * 上传图片到OSS服务
     * @param base64
     * @param folderName: 上传文件存放的文件夹名称,可选
     * @return 图片存储返回的url
     */
    public static String uploadImage(String base64, String folderName, String fileType) {
        return uploadImage(base64, folderName, "qncloudprintfile", fileType);
    }

    /***
     * 上传文件到OSS服务
     * @param multipartFile
     * @param folderName: 上传文件存放的文件夹名称,可选
     * @return 图片存储返回的url
     */
    public static String uploadFile(MultipartFile multipartFile, String folderName, String fileType) {
        return uploadImage(multipartFile, folderName, "qncloudprintfile", fileType);
    }

    /***
     * 上传私密文件到OSS服务
     * @param multipartFile
     * @param folderName: 上传文件存放的文件夹名称,可选
     * @return 图片存储返回的url
     */
    public static String uploadPrivateFile(MultipartFile multipartFile, String folderName) {
        return uploadImage(multipartFile, folderName, "qn-private");
    }

    /***
     * 上传私密文件到OSS服务
     * @param base64
     * @param folderName: 上传文件存放的文件夹名称,可选
     * @return 图片存储返回的url
     */
    public static String uploadPrivateFile(String base64, String folderName, String fileType) {
        return uploadImage(base64, folderName, "qn-private", fileType);
    }

    /**
     * 获取私密文件可访问url
     * @param url 文件url
     * @return
     */
    public static String getPrivateFileUrl(String url){
        // eg : http://medou.oss-cn-shenzhen.aliyuncs.com/saas/20200623160820.png
        url = url.replace("http://", "");
        url = url.replace("https://", "");
        String endpoint = url.substring(url.indexOf(".")+1, url.indexOf("/"));
        String bucketName = url.substring(0, url.indexOf("."));
        String objectName = url.substring(url.indexOf("/")+1);
        // 创建OSSClient实例。
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 设置URL过期时间为1小时。
        Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL accessUrl = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
        // 关闭OSSClient。
        ossClient.shutdown();
        return accessUrl.toString();
    }

    private static String uploadImage(MultipartFile multipartFile, String folderName, String bucketName) {
        String originalFileName = multipartFile.getOriginalFilename();
        String[] list = originalFileName.split("\\.");
        String type = list[list.length - 1];
        return uploadImage(multipartFile, folderName, bucketName, type);
    }

    /***
     * 上传图片到OSS服务
     * @param multipartFile
     * @param folderName: 上传文件存放的文件夹名称,可选
     * @return 图片存储返回的url
     */
    public static String uploadImage(MultipartFile multipartFile, String folderName, String bucketName, String type) {
        // 创建OSSClient实例。
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 上传文件流
        InputStream inputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (!SpringContextUtil.getActiveProfile().equals("pro")) {
            bucketName = bucketName + "test";
        }
        // 文件命名必须保证不能重名,否则覆盖
        Date date = new Date();
        String originalFileName = multipartFile.getOriginalFilename();
        if (type == null){
            String[] list = originalFileName.split("\\.");
            type = list[list.length - 1];
        }
        String objectName = date.getTime() + "." + type;
        if (folderName != null || folderName.length() > 0) {
            objectName = folderName + "/" + objectName; // 创建虚拟的文件夹
        }
        // 创建上传Object的Metadata
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(multipartFile.getSize());
        objectMetadata.setCacheControl("no-cache");
        objectMetadata.setHeader("Pragma", "no-cache");
//        String contentType = multipartFile.getContentType();
//        objectMetadata.setContentType(contentType);
        String contentType = "image/jpeg";

        if (type_contentType.containsKey(type)){
            contentType = type_contentType.get(type);
        }

        objectMetadata.setContentType(contentType);
        objectMetadata.setContentEncoding("utf-8");
        objectMetadata.setContentDisposition("inline;filename=" + objectName);

        PutObjectResult result = ossClient.putObject(bucketName, objectName, inputStream, objectMetadata);
        // 必须关闭OSSClient
        ossClient.shutdown();

        if (result.getETag() != null) {
            // 内网url "https://" + bucketName + ".oss-ap-southeast-1-internal.aliyuncs.com/" + objectName;
            // 外网url
            return "https://" + bucketName + ".oss-cn-shenzhen.aliyuncs.com/" + objectName;
            // CDN加速url
        }
        return null;
    }

    private static String uploadImage(String base64, String folderName, String bucketName, String fileType) {
        // 创建OSSClient实例。
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        if (!SpringContextUtil.getActiveProfile().equals("pro")) {
            bucketName = bucketName + "test";
        }
        // 文件命名必须保证不能重名,否则覆盖
        Date date = new Date();
        String objectName = date.getTime() + "." + fileType;
        if (folderName != null || folderName.length() > 0) {
            objectName = folderName + "/" + objectName; // 创建虚拟的文件夹
        }
       // byte[] bytes = Base64.decodeBase64(base64);
        byte[] bytes = Base64.getDecoder().decode(base64);

        PutObjectResult result = ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        // 必须关闭OSSClient
        ossClient.shutdown();

        if (result.getETag() != null) {
            // 内网url "https://" + bucketName + ".oss-ap-southeast-1-internal.aliyuncs.com/" + objectName;
            // 外网url
            return "https://" + bucketName + ".oss-cn-shenzhen.aliyuncs.com/" + objectName;
            // CDN加速url
        }
        return null;
    }

    /**
     * 删除文件
     * @param fileUrl
     */
    public static void deleteFile(String... fileUrl){
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 删除文件。key等同于ObjectName，表示删除OSS文件时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        List<String> keys = new ArrayList<>();
        String bucketName = null;
        for (String url : fileUrl){
            url = url.replace("http://", "");
            url = url.replace("https://", "");
            bucketName = url.substring(0, url.indexOf("."));
            keys.add(url.substring(url.indexOf("/")+1));
        }

        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();

        ossClient.shutdown();
    }
}
